<!DOCTYPE html>
<html>

<head>
  <title>Building Kafka Streams applications with Quarkus and Eclipse MicroProfile</title>
  <script id="adobe_dtm" src="https://www.redhat.com/dtm.js" type="text/javascript"></script>
  <script src="/assets/javascript/highlight.pack.js" type="text/javascript"></script>
  <META HTTP-EQUIV='Content-Security-Policy' CONTENT="default-src 'none'; script-src 'self' 'unsafe-eval' 'sha256-ANpuoVzuSex6VhqpYgsG25OHWVA1I+F6aGU04LoI+5s=' 'sha256-ipy9P/3rZZW06mTLAR0EnXvxSNcnfSDPLDuh3kzbB1w=' js.bizographics.com https://www.redhat.com assets.adobedtm.com jsonip.com https://ajax.googleapis.com https://www.googletagmanager.com https://www.google-analytics.com https://use.fontawesome.com; style-src 'self' https://fonts.googleapis.com https://use.fontawesome.com; img-src 'self' *; media-src 'self' ; frame-src https://www.googletagmanager.com https://www.youtube.com; frame-ancestors 'none'; base-uri 'none'; object-src 'none'; form-action 'none'; font-src 'self' https://use.fontawesome.com https://fonts.gstatic.com;">
  <META HTTP-EQUIV='X-Frame-Options' CONTENT="DENY">
  <META HTTP-EQUIV='X-XSS-Protection' CONTENT="1; mode=block">
  <META HTTP-EQUIV='X-Content-Type-Options' CONTENT="nosniff">
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="description" content="Quarkus: Supersonic Subatomic Java">
  <meta name="twitter:card" content="summary_large_image">
  <meta name="twitter:site" content="@QuarkusIO"> 
  <meta name="twitter:creator" content="@QuarkusIO">
  <meta property="og:url" content="https://quarkus.io/blog/kafka-streams-applications-with-quarkus-and-microprofile/" />
  <meta property="og:title" content="Building Kafka Streams applications with Quarkus and Eclipse MicroProfile" />
  <meta property="og:description" content="Quarkus: Supersonic Subatomic Java" />
  <meta property="og:image" content="/assets/images/quarkus_card.png" />
  <link rel="canonical" href="https://quarkus.io/blog/kafka-streams-applications-with-quarkus-and-microprofile/">
  <link rel="shortcut icon" type="image/png" href="/favicon.ico" >
  <link rel="stylesheet" href="https://quarkus.io/guides/stylesheet/config.css" />
  <link rel="stylesheet" href="/assets/css/main.css" />
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css" integrity="sha384-lKuwvrZot6UHsBSfcMvOkWwlCMgc0TaWr+30HWe3a4ltaBwTZhyTEggF5tJv8tbt" crossorigin="anonymous">
  <link rel="alternate" type="application/rss+xml"  href="https://quarkus.io/feed.xml" title="Quarkus">
  <script src="https://quarkus.io/assets/javascript/goan.js" type="text/javascript"></script>
  <script src="https://quarkus.io/assets/javascript/hl.js" type="text/javascript"></script>
</head>

<body class="post">
  <!-- Google Tag Manager (noscript) -->
  <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-NJWS5L"
  height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
  <!-- End Google Tag Manager (noscript) -->

  <div class="nav-wrapper">
  <div class="grid-wrapper">
    <div class="width-12-12">
      <input type="checkbox" id="checkbox" />
      <nav id="main-nav" class="main-nav">
  <div class="container">
    <div class="logo-wrapper">
      
        <a href="/"><img src="/assets/images/quarkus_logo_horizontal_rgb_600px_reverse.png" class="project-logo" title="Quarkus"></a>
      
    </div>
    <label class="nav-toggle" for="checkbox">
      <i class="fa fa-bars"></i>
    </label>
    <div id="menu" class="menu">
      <span>
        <a href="/get-started/" class="">Get Started</a>
      </span>
      <span>
        <a href="/guides/" class="">Guides</a>
      </span>
      <span>
        <a href="/community/" class="">Community</a>
      </span>
      <span>
        <a href="/support/" class="">Support</a>
      </span>
      <span>
        <a href="/blog/" class="active">Blog</a>
      </span>
      <span>
        <a href="https://code.quarkus.io" class="button-cta secondary white">Start Coding</a>
      </span>
    </div>
  </div>
      </nav>
    </div>
  </div>
</div>

  <div class="content">
    <div class="post-page grid-wrapper">
  <div class="width-8-12 width-12-12-m doc-content">
    <div class="grid-wrapper">
      <div class="width-12-12">
        <p>
          <a href="/blog"><i class="fas fa-angle-left"></i> Back to all posts</a>
        </p>
      </div>
      <div class="width-12-12">
        <div class="post-date">
          June 26, 2019 
          
            <span class="tags"><a href="/blog/tag/kafka">#kafka</a><a href="/blog/tag/microprofile">#microprofile</a></span>
          
        </div>
        <h1 class="post-title">Building Kafka Streams applications with Quarkus and Eclipse MicroProfile</h1>
        <div class="grid-wrapper">
          <div class="width-8-12 width-12-12-m byline-wrapper">
            
            
              <img class="headshot" src="https://www.gravatar.com/avatar/8e25c0ca4bf25113bd9c0ccc5d118164">
            
            <p class="byline">By Gunnar Morling</p>
          </div>
          <div class="width-12-12">
              <div class="paragraph">
<p><a href="https://kafka.apache.org/documentation/streams/">Kafka Streams</a> is a very popular solution for implementing stream processing applications based on Apache Kafka.
It lets you do typical data streaming tasks like filtering and transforming messages,
joining multiple Kafka topics, performing (stateful) calculations, grouping and aggregating values in time windows and much more.</p>
</div>
<div class="paragraph">
<p>Unlike other streaming query engines that run on specific processing clusters,
Kafka Streams is a client library.
This means a (Java) application is needed which starts and runs the streaming pipeline,
reading from and writing to the Apache Kafka cluster.</p>
</div>
<div class="paragraph">
<p>In this blog post we&#8217;ll discuss how the combination of Quarkus and <a href="https://microprofile.io/">Eclipse MicroProfile</a> is a great foundation for implementing Kafka Streams applications,
running on the JVM and as native code compiled ahead of time via <a href="https://www.graalvm.org/">GraalVM</a>.</p>
</div>
<div class="sect1">
<h2 id="the-quarkus-extension-for-kafka-streams"><a class="anchor" href="#the-quarkus-extension-for-kafka-streams"></a>The Quarkus extension for Kafka Streams</h2>
<div class="sectionbody">
<div class="paragraph">
<p>As of version 0.17.0, Quarkus comes with <a href="/guides/kafka-streams">an extension</a> for building Kafka Streams applications.
To create a new Quarkus project with this extension, run the following:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">mvn io.quarkus:quarkus-maven-plugin:0.17.0:create \
   -DprojectGroupId=org.acme \
   -DprojectArtifactId=kafka-streams-quickstart-example \
   -Dextensions="kafka-streams"</code></pre>
</div>
</div>
<div class="paragraph">
<p>This will set up a new project, adding the dependency to the Quarkus Kafka Streams extension,
which in turn will pull in Kafka Streams and all its dependencies.</p>
</div>
<div class="paragraph">
<p>If you&#8217;ve worked with Kafka Streams before, the implementation of a data streaming pipeline will look very familiar to you.
You first build up a <code>Topology</code> and then create a <code>KafkaStreams</code> instance.
For starting and stopping the latter, Quarkus' <code>StartupEvent</code> and <code>ShutdownEvent</code> classes come in handy.</p>
</div>
<div class="paragraph">
<p>Overall, the structure of a Kafka Streams pipeline running on Quarkus will look like so:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@ApplicationScoped
public class MyStreamingPipeline {

    private KafkaStreams streams;

    void onStart(@Observes StartupEvent event) {
        // set up Kafka Streams config, e.g. sourced from application.properties
        Properties props = new Properties();
        // props.put(..., ...);

        // set up the stream topology
        StreamsBuilder builder = new StreamsBuilder();
        // builder.stream(...)

        streams = new KafkaStreams(builder.build(), props);
        streams.start();
    }

    void onStop(@Observes ShutdownEvent event) {
        streams.close();
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>For the very common requirement that you&#8217;d like to serialize and deserialize Java types used in the streaming pipeline into/from JSON
(e.g. when materializing them in a state store),
the Quarkus Kafka Streams extension provides the class <code>io.quarkus.kafka.client.serialization.JsonbSerde</code>.
It&#8217;s a <code>Serde</code> implementation based on JSON-B:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">...
JsonbSerde&lt;WeatherStation&gt; weatherStationSerde = new JsonbSerde&lt;&gt;(WeatherStation.class);

GlobalKTable&lt;Integer, WeatherStation&gt; stations = builder.globalTable(
    "weather-stations",
    Consumed.with(Serdes.Integer(), weatherStationSerde)
);
...</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="running-native"><a class="anchor" href="#running-native"></a>Running Native</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Based on Kafka&#8217;s notion of topic partitioning, Kafka Streams applications can easily be scaled out:
the load will be shared amongst multiple instances of the application,
each processing just a subset of the partitions of the input topic(s).</p>
</div>
<div class="paragraph">
<p>Running Quarkus applications in native code via GraalVM comes in very handy for that:
besides the very fast start-up time, the applications will use significantly less memory when compiled to native code.
This lets you spin up many instances of a Quarkus-based Kafka Streams pipeline in parallel,
in a very memory-efficient way.</p>
</div>
<div class="paragraph">
<p>The extension takes care of everything needed for building native Kafka Streams applications,
for instance it makes sure that the right RocksDB native libraries are added to the application image.
All you need to do is to specify the <code>enableJni</code> option for the Quarkus Maven plug-in,
allowing those native libraries to be invoked via JNI:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="xml" class="language-xml hljs">&lt;plugin&gt;
    &lt;groupId&gt;io.quarkus&lt;/groupId&gt;
    &lt;artifactId&gt;quarkus-maven-plugin&lt;/artifactId&gt;
    &lt;executions&gt;
        &lt;execution&gt;
            &lt;goals&gt;
                &lt;goal&gt;native-image&lt;/goal&gt;
            &lt;/goals&gt;
            &lt;configuration&gt;
                &lt;enableJni&gt;true&lt;/enableJni&gt;
            &lt;/configuration&gt;
        &lt;/execution&gt;
    &lt;/executions&gt;
&lt;/plugin&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>When using the <code>JsonbSerde</code> for unmarshalling JSON into corresponding Java objects,
those types must be marked with the <code>@RegisterForReflection</code> annotation,
so that they can to be instantiated reflectively by JSON-B in native mode:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@RegisterForReflection
public class WeatherStation {

    public int id;
    public String name;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Then build the application using the <code>native</code> profile
(note this requires GraalVM to be installed on your system; refer to the Quarkus <a href="/guides/building-native-image">native image</a> guide to learn more):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">mvn clean package -f aggregator/pom.xml -Pnative</code></pre>
</div>
</div>
<div class="paragraph">
<p>Finding the right amount of memory needed for running the application can require some testing.
E.g. observe CPU load and run the native binary with the <code>-XX:+PrintGC -XX:+PrintGCTimeStamps -XX:+VerboseGC</code> options
in order to gain insight into how often garbage collection kicks in.
If you started the application with not enough heap space,
you&#8217;ll typically observe that GC is happening very frequently, causing increased CPU load.</p>
</div>
<div class="paragraph">
<p>To give an example, for the <a href="https://github.com/quarkusio/quarkus-quickstarts/tree/master/kafka-streams-quickstart">streaming pipeline</a> discussed in the Kafka Streams extension guide,
a heap size of 32 MB (<code>-Xmx32m</code>) works very well,
resulting in less than 50 MB memory needed by the process in total
(RSS, resident set size).
Note that this number also contains the memory needed for the HTTP endpoint defined in that example,
which is used for answering interactive queries via REST.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="gaining-operational-insight"><a class="anchor" href="#gaining-operational-insight"></a>Gaining Operational Insight</h2>
<div class="sectionbody">
<div class="paragraph">
<p>One of the nice things about Quarkus is that it comes with support for all the Eclipse MicroProfile APIs.
They help to address common requirements when building microservices,
such as <a href="https://microprofile.io/project/eclipse/microprofile-health">health checks</a> ("Is my application running and ready to handle requests?")
and <a href="https://microprofile.io/project/eclipse/microprofile-metrics">metrics</a> ("What&#8217;s the throughput of my application?", "How many requests has it processed?" etc.).</p>
</div>
<div class="paragraph">
<p>Based on those APIs,
it just requires a little bit of coding to implement health checks and metrics for a Kafka Streams application.
You can add the right dependencies by running:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">./mvnw quarkus:add-extension -Dextensions="health,metrics"</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="healthchecks"><a class="anchor" href="#healthchecks"></a>Healthchecks</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Then creating the health check is as simple as adding the following to the pipeline implementation:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Liveness
@ApplicationScoped
public class MyStreamingPipeline implements HealthCheck {

    private KafkaStreams streams;

    // ...

    @Override
    public HealthCheckResponse call() {
        return HealthCheckResponse.named("My Pipeline")
                .state(streams.state().isRunning())
                .build();
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>This will expose a health check via HTTP under <code>/health/live</code>,
which when queried will yield a response like this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="json" class="language-json hljs">HTTP/1.1 200 OK
Connection: keep-alive
Content-Length: 144
Content-Type: application/json;charset=UTF-8
Date: Wed, 26 Jun 2019 10:08:36 GMT

{
    "checks": [
        {
            "name": "My Pipeline",
            "status": "UP"
        }
    ],
    "status": "UP"
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>When using a container orchestrator such as Kubernetes,
you could then set up a <a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/">liveness probe</a> for this endpoint.
If the health check fails (i.e. the streaming pipeline is not in the running state),
it will return an HTTP 503 response.
This would be the indicator to the orchestrator to restart the pod of this application.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="metrics"><a class="anchor" href="#metrics"></a>Metrics</h2>
<div class="sectionbody">
<div class="paragraph">
<p>While a health check provides simple means of finding out whether the application is in a state where it can handle requests/messages or not,
it is desirable to have more insight into the behaviour of the service.
E.g. it might be of interest to see how many messages have been processed by the streaming pipeline,
what&#8217;s the arrival rate of messages, what&#8217;s the average processing time and much more.</p>
</div>
<div class="paragraph">
<p>Kafka Streams comes with <a href="https://kafka.apache.org/22/javadoc/org/apache/kafka/streams/KafkaStreams.html#metrics--">rich metrics</a> capabilities which can help to answer these questions.
Using the MicroProfile Metrics API, these metrics can be exposed via HTTP.
From there they can be scraped by tools such as <a href="https://prometheus.io/">Prometheus</a> and eventually be fed to dashboard solutions such as <a href="https://grafana.com/">Grafana</a>.
Note that exposing metrics via HTTP instead of JMX has the advantage that this also works when running the application in native mode via GraalVM.</p>
</div>
<div class="paragraph">
<p>Similar to the health check case, just a bit of glue code is needed for exposing the metrics:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@ApplicationScoped
public class MyStreamingPipeline {

    @Inject
    MetricRegistry metricRegistry;

    private KafkaStreams streams;

    void onStart(@Observes StartupEvent event) {
        // ...

        streams.start();
        exportMetrics();
    }

    // ...

    private void exportMetrics() {
        Set&lt;String&gt; processed = new HashSet&lt;&gt;();

        for (Metric metric : streams.metrics().values()) {                <i class="conum" data-value="1"></i><b>(1)</b>
            String name = metric.metricName().group() +
                    ":" + metric.metricName().name();

            if (processed.contains(name)) {
                continue;
            }

            // string-typed metric not supported
            if (name.contentEquals("app-info:commit-id") ||               <i class="conum" data-value="2"></i><b>(2)</b>
                    name.contentEquals("app-info:version")) {
                continue;
            }
            else if (name.endsWith("count") || name.endsWith("total")) {  <i class="conum" data-value="3"></i><b>(3)</b>
                registerCounter(metric, name);
            }
            else {
                registerGauge(metric, name);                              <i class="conum" data-value="4"></i><b>(4)</b>
            }

            processed.add(name);
        }
    }

    private void registerGauge(Metric metric, String name) {
        Metadata metadata = new Metadata(name, MetricType.GAUGE);
        metadata.setDescription(metric.metricName().description());

        metricRegistry.register(metadata, new Gauge&lt;Double&gt;() {

            @Override
            public Double getValue() {
                return (Double) metric.metricValue();
            }
        } );
    }

    private void registerCounter(Metric metric, String name) {
        // ...
    }
}</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>Process all Kafka Streams metrics, using a unique name to register them</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>Some string-typed "metrics" must be excluded</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>All metrics whose name ends with "total" or "counter" will be exposed as counter-typed metrics</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>All other metrics will be exposed as gauge-typed metrics, i.e. plain numeric values</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Once the application is started, the metrics will be exposed under <code>/metrics</code>,
returning the data in the OpenMetrics format by default:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs"># HELP application:stream_metrics_process_total The total number of occurrence of process operations.
# TYPE application:stream_metrics_process_total counter
application:stream_metrics_process_total 2866.0
# HELP application:stream_metrics_poll_latency_avg The average latency of poll operation.
# TYPE application:stream_metrics_poll_latency_avg gauge
application:stream_metrics_poll_latency_avg 83.3135593220339
# ...</code></pre>
</div>
</div>
<div class="paragraph">
<p>From here it&#8217;s a matter of minutes to set up Prometheus to scrape this target,
configure a Prometheus data source in Grafana and configure a dashboard for visualizing the metrics of interest to you.
E.g. the following shows a simple dashboard displaying the poll/process/commit rates and latencies as well as the total number of processed events
in the quickstart example:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="/assets/images/kafka-streams-metrics.png" alt="Kafka Streams metrics in Grafana">
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="summary-and-outlook"><a class="anchor" href="#summary-and-outlook"></a>Summary and Outlook</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Quarkus and Eclipse MicroProfile are a great basis for building Kafka Streams applications.
The Quarkus extension for Kafka Streams comes with everything needed to run stream processing pipelines on the JVM as well as in native mode via GraalVM.
The MicroProfile APIs for health checks and metrics can be used to expose the right information
for gaining insight into running stream processing applications.</p>
</div>
<div class="paragraph">
<p>Going forward, we plan to further reduce the efforts needed for building Kafka Streams applications on Quarkus.
Instead of having to deal with the lifecycle of the pipeline yourself,
it should be enough to declare a CDI producer method returning the streaming <code>Topology</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">@Produces
public Topology buildTopology()  {
    // set up the stream topology
    StreamsBuilder builder = new StreamsBuilder();
    // builder.stream(...)

    return builder.build();
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>This means you&#8217;ll be able to focus on implementing the actual pipeline logic,
while the Quarkus extension would take care of everything else:
configuring Kafka Streams based on the Quarkus <code>application.properties</code> file,
starting the pipeline and automatically exposing healthchecks and metrics.</p>
</div>
<div class="paragraph">
<p>In case this sounds interesting to you, have an eye on the next Quarkus release announcements,
as this improved functionality should be out soon.
If you got any related ideas, let us know and join the discussion in Quarkus issue <a href="https://github.com/quarkusio/quarkus/issues/2863">#2863</a>.</p>
</div>
<div class="paragraph">
<p>To learn more about the Quarkus extension for Kafka Streams and its current capabilities,
check out <a href="/guides/kafka-streams">the detailed guide</a>.
It not only discusses the actual stream pipeline implementation, but also touches on
building (distributed) interactive queries for exposing the current processing state via REST.</p>
</div>
</div>
</div>
              
          </div>
          <div class="width-12-12"><div class="share-page">
  <a class="share-linkedin" href="https://www.linkedin.com/shareArticle?mini=true&url=https://quarkus.io/blog/kafka-streams-applications-with-quarkus-and-microprofile/&title=Building Kafka Streams applications with Quarkus and Eclipse MicroProfile" rel="nofollow" target="_blank" title="Share on LinkedIn">
    <img src="/assets/images/share-page/icons_social-linkedin.png"/>
  </a>
  <a class="share-twitter" href="https://twitter.com/intent/tweet?text=Building Kafka Streams applications with Quarkus and Eclipse MicroProfile&url=https://quarkus.io/blog/kafka-streams-applications-with-quarkus-and-microprofile/&via=quarkusio&related=quarkusio" rel="nofollow" target="_blank" title="Share on Twitter">
    <img src="/assets/images/share-page/icons_social-twitter.png"/>
  </a>
  <a class="share-facebook" href="https://facebook.com/sharer.php?u=https://quarkus.io/blog/kafka-streams-applications-with-quarkus-and-microprofile/" rel="nofollow" target="_blank" title="Share on Facebook">
    <img src="/assets/images/share-page/icons_social-facebook.png"/>
  </a>
  <a class="share-reddit" href="http://www.reddit.com/submit?url=https://quarkus.io/blog/kafka-streams-applications-with-quarkus-and-microprofile/" onclick="window.open(this.href, 'pop-up', 'left=20,top=20,width=900,height=500,toolbar=1,resizable=0'); return false;" title="Share on Reddit" >
    <img src="/assets/images/share-page/icons_social-reddit.png"/>
  </a>
  <a class="share-email" href="mailto:?subject=Building Kafka Streams applications with Quarkus and Eclipse MicroProfile&amp;body=Building Kafka Streams applications with Quarkus and Eclipse MicroProfile https://quarkus.io/blog/kafka-streams-applications-with-quarkus-and-microprofile/" title="Share via Email" >
    <img src="/assets/images/share-page/icons_social-email.png"/>
  </a>
</div>
</div>
        </div>
      </div>
    </div>
  </div>
</div>

  </div>

  <div class="content project-footer">
  <div class="footer-section">
    <div class="logo-wrapper">
      <a href="/"><img src="/assets/images/quarkus_logo_horizontal_rgb_reverse.svg" class="project-logo" title="Quarkus"></a>
    </div>
  </div>
  <div class="grid-wrapper">
    <p class="grid__item width-3-12">Quarkus is open. All dependencies of this project are available under the <a href='https://www.apache.org/licenses/LICENSE-2.0' target='_blank'>Apache Software License 2.0</a> or compatible license.<br /><br />This website was built with <a href='https://jekyllrb.com/' target='_blank'>Jekyll</a>, is hosted on <a href='https://pages.github.com/' target='_blank'>Github Pages</a> and is completely open source. If you want to make it better, <a href='https://github.com/quarkusio/quarkusio.github.io' target='_blank'>fork the website</a> and show us what you’ve got.</p>

    
      <div class="width-1-12 project-links">
        <span>Navigation</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="/">Home</a></li>
          
            <li><a href="/guides">Guides</a></li>
          
            <li><a href="/community/#contributing">Contribute</a></li>
          
            <li><a href="/faq">FAQ</a></li>
          
            <li><a href="/get-started">Get Started</a></li>
          
        </ul>
      </div>
    
      <div class="width-1-12 project-links">
        <span>Contribute</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="https://twitter.com/quarkusio">Follow us</a></li>
          
            <li><a href="https://github.com/quarkusio">GitHub</a></li>
          
            <li><a href="/security">Security&nbsp;policy</a></li>
          
        </ul>
      </div>
    
      <div class="width-1-12 project-links">
        <span>Get Help</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="https://groups.google.com/forum/#!forum/quarkus-dev">Forums</a></li>
          
            <li><a href="https://quarkusio.zulipchat.com">Chatroom</a></li>
          
        </ul>
      </div>
    

    
      <div class="width-3-12 more-links">
        <span>Quarkus is made of community projects</span>
        <ul class="footer-links">
          
            <li><a href="https://vertx.io/" target="_blank">Eclipse Vert.x</a></li>
          
            <li><a href="https://microprofile.io" target="_blank">Eclipse MicroProfile</a></li>
          
            <li><a href="https://hibernate.org" target="_blank">Hibernate</a></li>
          
            <li><a href="https://netty.io" target="_blank">Netty</a></li>
          
            <li><a href="https://resteasy.github.io" target="_blank">RESTEasy</a></li>
          
            <li><a href="https://camel.apache.org" target="_blank">Apache Camel</a></li>
          
            <li><a href="https://code.quarkus.io/" target="_blank">And many more...</a></li>
          
        </ul>
      </div>
    
  </div>
</div>
  <div class="content redhat-footer">
  <div class="grid-wrapper">
    <span class="licence">
      <i class="fab fa-creative-commons"></i><i class="fab fa-creative-commons-by"></i> <a href="https://creativecommons.org/licenses/by/3.0/" target="_blank">CC by 3.0</a> | <a href="https://www.redhat.com/en/about/privacy-policy">Privacy Policy</a>
    </span>
    <span class="redhat">
      Sponsored by
    </span>
    <span class="redhat-logo">
      <a href="https://www.redhat.com/" target="_blank"><img src="/assets/images/redhat_reversed.svg"></a>
    </span>
  </div>
</div>


  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" integrity="sha384-8gBf6Y4YYq7Jx97PIqmTwLPin4hxIzQw5aDmUg/DDhul9fFpbbLcLh3nTIIDJKhx" crossorigin="anonymous"></script>
  <script type="text/javascript" src="/assets/javascript/mobile-nav.js"></script>
  <script type="text/javascript" src="/assets/javascript/scroll-down.js"></script>
  <script src="/assets/javascript/satellite.js" type="text/javascript"></script>
  <script src="https://quarkus.io/guides/javascript/config.js" type="text/javascript"></script>
  <script src="/assets/javascript/search-filter.js" type="text/javascript"></script>
  <script src="/assets/javascript/back-to-top.js" type="text/javascript"></script>
</body>

</html>
